package com.sikulifang.bank.simulation.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.sql.SqlBuilder;
import com.sikulifang.bank.simulation.dto.QueryCriteriaDTO;
import com.sikulifang.bank.simulation.enums.BankEnum;
import com.sikulifang.bank.simulation.service.IAccountService;
import com.sikulifang.bank.simulation.service.IDetailService;
import com.sikulifang.bank.simulation.util.R;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * ClassName AccountServiceImpl
 * Description AccountServiceImpl
 *
 * @author Yat
 * Date 2023年6月9日, 0009 17:12
 * version 1.0
 */
@Slf4j
@Service
public class AccountServiceImpl extends ServiceImpl implements IAccountService {

    @Resource
    private IDetailService detailService;

    @Override
    public List<String> getQueryCriteria() {
        return ListUtil.toList("card_id", "account_name", "open_bank_name", "open_bank_no", "bank_code");
    }

    @Override
    public List<String> findAccountNameByBankName(String bankName) {
        List<Entity> query = findAll(bankName, null);

        return query.stream().map(obj -> obj.get("account_name", ""))
                .filter(StrUtil::isNotBlank).distinct().toList();
    }

    @Override
    public List<String> findAccountNoByBankName(String accountName, String bankName) {
        List<Entity> query = findAll(bankName, accountName);

        return query.stream().map(obj -> obj.get("card_id", ""))
                .filter(StrUtil::isNotBlank).toList();
    }

    @Override
    @SneakyThrows
    public R<String> save(Entity entity) {
        if (ObjectUtil.isEmpty(entity.get("card_id"))) {
            return R.failed("账号不能为空！");
        }
        Entity get = db.get(Entity.create(getTableName()).set("card_id", entity.get("card_id")));
        if (null != get) {
            return R.failed("存在相同的账号！");
        }
        db.insert(entity);
        return R.ok();
    }

    @Override
    @SneakyThrows
    public void recharge(String id, BigDecimal money) {
        db.execute("UPDATE account SET money = money + " + money + " WHERE id =" + id);

        Entity entity = db.get(Entity.create(getTableName()).set("id", id));
        String code = entity.getStr("bank_code");

        String bankCode = "";
        for (BankEnum value : BankEnum.values()) {
            if (code.contains(value.name())) {
                bankCode = value.name();
                break;
            }
        }

        Dict dict = new Dict();
        dict.set("status", 1);
        dict.set("statusText", "系统充值");
        dict.set("money", money);
        // 自己的账号 
        dict.set("card_id", entity.get("card_id"));

        // 自己账号名称
        dict.set("account_name", entity.get("account_name"));
        // 自己开户行名称
        dict.set("open_bank_name", entity.get("open_bank_name"));
        // 余额
        dict.set("balance", entity.get("money"));
        // 对方账号
        dict.set("oppAccountNo", "1111111111111111111");
        dict.set("bankNo", "111111111111");

        // 对方账户名称
        dict.set("oppAccountName", "系统账号");
        // 对方开户行名
        dict.set("oppOpenBankName", "系统账号");
        // 对方开户 行 号
        dict.set("oppBankNo", "111111");

        String serialNo = IdUtil.getSnowflakeNextIdStr();

        dict.set("type", 3);
        dict.set("money", money);
        dict.set("flag", "C");
        dict.set("postScript", "系统充值金额");
        dict.set("summary", "系统充值金额");
        dict.set("useCn", "系统充值金额");
        dict.set("serialNo", serialNo);
        dict.set("batchSerialNo", serialNo);

        Date date = new Date();
        String tran_date = DateUtil.format(date, DatePattern.PURE_DATE_PATTERN);
        String tran_time = DateUtil.format(date, DatePattern.PURE_TIME_PATTERN);

        dict.set("tranDate", tran_date);
        dict.set("tranTime", tran_time);
        dict.set("createTime", DateUtil.formatDateTime(date));

        detailService.updateDetail(dict, bankCode, Boolean.TRUE);

    }


    @Override
    @SneakyThrows
    public Dict findAll(String account) {

        List<Entity> all;
        if (StrUtil.isNotBlank(account)) {
            SqlBuilder builder = getSqlBuilder();
            builder.append(" and card_id <> " + account);
            all = db.query(builder.build());
        } else {
            all = db.findAll(getTableName());
        }

        Map<String, Map<String, Set<String>>> groupMap = new HashMap<>();

        // 根据账号的所属银行名称，用户 分组
        for (Entity entity : all) {
            String bankCode = entity.getStr("bank_code");
            Map<String, Set<String>> accountNameMap = groupMap.get(bankCode);
            if (accountNameMap == null) {
                accountNameMap = new HashMap<>();
            }

            String accountName = entity.getStr("account_name");
            Set<String> set = accountNameMap.get(accountName);
            if (set == null) {
                set = new HashSet<>();
            }

            set.add(entity.getStr("card_id"));

            accountNameMap.put(accountName, set);
            groupMap.put(bankCode, accountNameMap);
        }

        List<Dict> dictList = new ArrayList<>();

        // 分组完成后，把Map转成树
        for (String bankCode : groupMap.keySet()) {
            Map<String, Set<String>> accountNameMap = groupMap.get(bankCode);
            List<Dict> dictList2 = new ArrayList<>();
            for (String accountName : accountNameMap.keySet()) {

                List<Dict> collect = accountNameMap.get(accountName).stream().map(obj -> {
                    Dict dict = new Dict();
                    dict.set("label", obj);
                    dict.set("value", obj);
                    return dict;
                }).toList();

                Dict dict = new Dict();
                dict.set("label", accountName);
                dict.set("value", accountName);
                dict.set("children", collect);

                dictList2.add(dict);
            }

            Dict dict = new Dict();
            dict.set("label", bankCode);
            dict.set("value", bankCode);
            dict.set("children", dictList2);

            dictList.add(dict);
        }

        Dict dict = new Dict();
        dict.set("data", dictList);
        return dict;
    }

    /**
     * 查询所有的信息
     *
     * @param bankName    银行名称
     * @param accountName 账号名称
     */
    @SneakyThrows
    private List<Entity> findAll(String bankName, String accountName) {

        SqlBuilder builder = getSqlBuilder();
        if (StrUtil.isNotBlank(accountName)) {
            builder.append(" and account_name = " + accountName);
        }
        if (StrUtil.isNotBlank(bankName)) {
            builder.append(" and bank_code = " + bankName);
        }
        return db.query(builder.build());
    }

    @Override
    public Entity list(QueryCriteriaDTO queryCriteria) {
        Entity entity = super.list(queryCriteria);
        if (entity.get(dbProperties.getRecords()) instanceof List<?> dictList) {
            for (Object obj : dictList) {
                if (obj instanceof Dict data) {
                    Object money = data.get("money");
                    if (ObjectUtil.isEmpty(money)) {
                        money = 0;
                    }
                    data.set("money", new DecimalFormat("0.000000").format(money));
                }
            }
        }
        return entity;
    }
}
